
/*
 * utils.c
 *
 *  Created on: 28/06/2011
 *      Author: fviale
 */

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unicode/utypes.h>
#include <unicode/ustring.h>
#include "utils.h"
#include "conexiones.h"
#include "nipc.h"


//! Byte swap unsigned short
uint16_t swap_uint16(uint16_t val) {
	return (val << 8) | (val >> 8);
}

//! Byte swap signed short
int16_t swap_int16(int16_t val) {
	return (val << 8) | ((val >> 8) & 0xFF);
}

//! Byte swap unsigned int
uint32_t swap_uint32(uint32_t val) {
	val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
	return (val << 16) | (val >> 16);
}

//! Byte swap int
int32_t swap_int32(int32_t val) {
	val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
	return (val << 16) | ((val >> 16) & 0xFFFF);
}

uint16_t *unicode_utf8_to_utf16(const char *src_utf8, const size_t src_utf8size, size_t *dest_utf16size) {
	UErrorCode error = U_ZERO_ERROR;

	uint16_t utf16_buff[(src_utf8size + 1) * 2];
	uint16_t *utf16 = NULL;

	u_strFromUTF8(utf16_buff, (src_utf8size + 1) * 2, dest_utf16size, src_utf8, src_utf8size, &error);

	if (error != U_ZERO_ERROR) {
		return NULL;
	}

	utf16 = malloc(*dest_utf16size);
	memcpy(utf16, utf16_buff, *dest_utf16size);

	return utf16;
}

int unicode_utf8_to_utf16_inbuffer(const char *src_utf8, const size_t src_utf8size, uint16_t *dest_utf16, size_t *dest_utf16size) {
	UErrorCode error = U_ZERO_ERROR;

	u_strFromUTF8(dest_utf16, (src_utf8size + 1) * 2, dest_utf16size, src_utf8, src_utf8size, &error);

	if (error != U_ZERO_ERROR) {
		return 0;
	}

	return 1;
}

char *unicode_utf16_to_utf8(const uint16_t *src_utf16, const size_t src_utf16size, size_t *dest_utf8size) {
	UErrorCode error = U_ZERO_ERROR;

	char utf8_buff[src_utf16size + 1];char
	*utf8 = NULL;

	u_strToUTF8(utf8_buff, src_utf16size + 1, dest_utf8size, src_utf16, src_utf16size, &error);

	if (error != U_ZERO_ERROR) {
		return NULL;
	}

	utf8 = malloc(*dest_utf8size);
	memcpy(utf8, utf8_buff, *dest_utf8size);

	return utf8;
}

int unicode_utf16_to_utf8_inbuffer(const uint16_t *src_utf16, const size_t src_utf16size, char* dest_utf8, size_t *dest_utf8size) {
	UErrorCode error = U_ZERO_ERROR;

	u_strToUTF8(dest_utf8, src_utf16size + 1, dest_utf8size, src_utf16, src_utf16size, &error);

	if (error != U_ZERO_ERROR) {
		return 0;
	}

	return 1;
}

char** string_split2( char *str, char delimitor ){
	char **array;
	int elementsAmount = 0;

	{
		int cont;
		for(cont=0; str[cont] != '\0'; cont++ ){
			if( str[cont] == delimitor)	elementsAmount++;
		}
		elementsAmount++;
	}

	{
		array = calloc(elementsAmount+1, sizeof(char*) );
	}

	{
		int pibot, length, cont, elementIndex;
		for(cont=0, pibot=0, length=0, elementIndex=0; elementIndex != elementsAmount ; cont++ ){
			if( str[cont] == delimitor || str[cont] == '\0' ){
				array[elementIndex] = malloc(length + 1);
				if( length > 0 ){
					strncpy(array[elementIndex], &str[pibot], length);
					array[elementIndex][length] = '\0';
				} else {
					array[elementIndex][0] = '\0';
				}
				pibot = pibot + length + 1;
				length = 0;
				elementIndex++;
			} else {
				length++;
			}
		}
		array[elementIndex] = NULL;
	}
	return array;
}

void string_split3( char *str, char delimitor, char **result ){
	int pibot, length, cont, elementIndex = 0;

	for(cont=0, pibot=0, length=0; str[cont] != '\0' ; cont++ ){

		if( str[cont] == delimitor ){
			if( length > 0 ){
				memcpy(result[elementIndex], &str[pibot], length);
				result[elementIndex][length] = '\0';
			} else {
				result[elementIndex][0] = '\0';
			}
			pibot = pibot + length + 1;
			length = 0;

			elementIndex++;
		} else {
			length++;
		}
	}

	memcpy(result[elementIndex], &str[pibot], length);

	result[elementIndex + 1] = NULL;
}

/*
 * utils.c
 *
 *  Created on: 21/10/2011
 *      Author: Pablo Arias & Juan Pablo De Blas
 */

t_conexion *conexiones;

int connect_Raid_PPD(){

	char processip[16];
	int  fdSock, maxconexiones, i, retval;
	nipcMessage msg;
	unsigned short processport;

	memset(processip, 0, 16);

	getConfig("processip", &processip);
	getConfig("processport", &processport);
	getConfig("maxconexiones", &maxconexiones);

	conexiones = malloc(maxconexiones * sizeof(t_conexion));

	for(i=0; i<maxconexiones; i++)
	{
		if(-1 == (fdSock = sockets_open_client(processip, processport)))
				{
					printf("Error al abrir el socket para conectar con el proceso.\n");
					return -1;
				}

		nipc_make(&msg, fdSock, '0', 0, NULL);
		nipc_send(&msg, fdSock);
		retval = nipc_recv(&msg, fdSock);
		if((NIPC_ERROR_NONE != retval) || (msg.payload == HANDSHAKE_FAIL))
			{
				printf("Error en el handshake con el raid/PPD.\n");
				close(fdSock);
				return -1;
			}
		conexiones[i].socket = fdSock;
		conexiones[i].libre = FREE;
	}

	return 0;
}

unsigned int concat_uint(char numers[],unsigned int length){
	char aux[length],ret[1]="\0",*ptr=NULL;
	int i;
	memset(aux,0,length);
	for(i=0;i<length;i++){
		sprintf(ret,"%d",numers[i]);
		ptr=strcat(aux,ret);
	}
	return strtoul(aux,&ptr,10);
}


// potencia2: hace una potencia con base 2 elevado a la n.
unsigned int potencia2(char n){
        unsigned int resultado = 1;
        int i;
        for(i = 1; i <= n; i++){
                resultado = resultado * 2;
        }
        return resultado;
}


// byteToBin: Pasa un byte a binario.
char *byteToBin(char n){
        int i;
        static char ret[8];

        for(i=0; i < 8; i++)
        {
                if((n & potencia2(7 - i)) == potencia2(7 - i))
                        ret[i] = '1';

                else
                        ret[i] = '0';
        }
        return ret;
}

// binToByte: pasa un byte en binario a decimal, espera como argumento el numero y su longitud EN BITS!
unsigned int binToByte(char *n,char len){
        unsigned int resultado = 0;
        int i;
        for(i = 0; i < len; i++)
        {
                if( n[i] == '1')
                resultado = resultado + potencia2((len-1) - i);

        }
        return resultado;

}

//Pasa un conjunto de bytes a decimal usando Big Endian.. espera el conjunto y su longitud EN BYTES!!!
unsigned int toBigEndian(char *bytes, char len){
        char *cadena;
        cadena = malloc( len*sizeof(char) );
        *cadena = 0;
        int i;

        for(i=0; i < len; i++){
        	strcat(cadena,byteToBin(bytes[i]));
        }

        return binToByte(cadena,8*len);
}

//Pasa un conjunto de bytes a decimal usando Little Endian.. espera el conjunto y su longitud EN BYTES!!!
unsigned int toLilEndian(char bytes[], char len){
        char *cadena;
        cadena = malloc( len*sizeof(char) );
        *cadena = 0;
        int i;

        for(i= len -1; i >= 0; i--){
        	strcat(cadena,byteToBin(bytes[i]));
        }

        return binToByte(cadena,8*len);
}

int intlen(float start) {
    int end = 0;
    while(start > 0) {
        start = start/10;
        end++;
    }
    if (end == 0)
    	return 1;
    else
    	return end - 45 ;
}
